package com.minelx.table.core.series.source;

import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public interface GridSource<E> {
	E at(long rowAt, long columnAt);

	long availableRow();

	long availableColumn();

	default Stream<E> rowValues(long rowAt) {
		return orderedStream(iterateRow(rowAt));
	}

	default Stream<E> columnValues(long columnAt) {
		return orderedStream(iterateColumn(columnAt));
	}

	default Iterator<E> iterateRow(long rowAt) {
		return new Iterator<E>() {
			private final long maxColumn = availableColumn();

			private int columnAt;

			@Override
			public boolean hasNext() {
				return columnAt < maxColumn;
			}

			@Override
			public E next() {
				E result = at(rowAt, columnAt);
				columnAt++;
				return result;
			}
		};
	}

	default Iterator<E> iterateColumn(long columnAt) {
		return new Iterator<E>() {
			private final long maxRow = availableRow();

			private int rowAt;

			@Override
			public boolean hasNext() {
				return rowAt < maxRow;
			}

			@Override
			public E next() {
				E result = at(rowAt, columnAt);
				rowAt++;
				return result;
			}
		};
	}

	static <E> Stream<E> orderedStream(Iterator<E> iterator) {
		// FIXME 2021/8/13  wait for me!!!      known sized spliterator is faster
		Spliterator<E> spliterator = Spliterators.spliteratorUnknownSize(
				iterator,
				Spliterator.ORDERED
		);
		return StreamSupport.stream(spliterator, false);
	}
}
